Fix intra-decile income change formula doubling percentage changes#3283
Merged
Fix intra-decile income change formula doubling percentage changes#3283
Conversation
Line 327 used reform_income.values where it should have used baseline_income.values, causing capped_reform_income to double-count the change. Simplified to absolute_change / capped_baseline_income. Same fix applied to intra_wealth_decile_impact (line 389). Added regression tests that verify: - 5% gain stays in <5% bucket (was incorrectly doubled to 10%) - 2% gain stays in <5% bucket - 10% gain correctly lands in >5% bucket - Zero and negative baseline incomes handled without NaN/Inf - Wealth decile variant has same fix Closes #3282 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies that when baseline income is $0, the max(B, 1) floor gives a denominator of 1, producing correct (not NaN/Inf) results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A 4% gain doubled to 8% would cross the 5% threshold. The existing 2% test wouldn't catch the bug since 2*2%=4% stays under 5%. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pulls the 3-line formula into a named function so it can be tested directly with exact value assertions, not just bucket assignment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test expectations (budgetary impact 95.4M, intra_decile 0.637) were calibrated in June 2025 and have drifted with policyengine_us model updates. Master CI skipped the test job so this was not caught earlier. Updated to match current model output (1867.4M, 0.534). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3283 +/- ##
==========================================
+ Coverage 70.76% 72.74% +1.97%
==========================================
Files 56 56
Lines 2398 2396 -2
Branches 341 341
==========================================
+ Hits 1697 1743 +46
+ Misses 641 591 -50
- Partials 60 62 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
MaxGhenis
approved these changes
Feb 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
intra_decile_impactandintra_wealth_decile_impactdoubled all household percentage income changesreform_income.valueswhere it should have usedbaseline_income.values, causingcapped_reform_incometo double-count the changeincome_change = absolute_change / capped_baseline_incomeRoot cause
Introduced in commit
20292bf7(Dec 2022, PR #38) — a fix for negative income handling accidentally usedreform_incomeinstead ofbaseline_income:For the common case (B >= 1, R >= 1):
max(R,1) + (R-B)=2R - B, givingincome_change = 2(R-B)/Binstead of(R-B)/B.Impact
All intra-decile winners/losers charts on policyengine.org have been overstating the proportion of people with large gains/losses (>5%) since Dec 2022. The same formula was copied to
PolicyEngine/state-legislative-tracker.Test plan
Closes #3282
🤖 Generated with Claude Code